package com.example.lgseckill.controller;

import com.example.lgseckill.commom.Constant;
import com.example.lgseckill.commom.rocketmq.RocketMQProducer;
import com.example.lgseckill.commom.utils.RedisUtil;
import com.example.lgseckill.commom.utils.Result;
import com.example.lgseckill.commom.utils.SnowFlake;
import com.example.lgseckill.domain.SeckillOrder;
import com.example.lgseckill.domain.SeckillProductPreheatVO;
import com.example.lgseckill.service.ISeckillOrderService;
import com.example.lgseckill.service.ISeckillService;
import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.SendCallback;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.remoting.exception.RemotingException;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.nio.charset.StandardCharsets;
import java.util.Date;


/**
 * Author:e
 * 秒杀入口
 * Date:2021/8/17 8:57 下午
 **/
@RestController
@RequestMapping("/seckill")
public class SeckillController {
    private final static Logger logger = LoggerFactory.getLogger(SeckillController.class);


    @Autowired
    private ISeckillService seckillService;
    @Autowired
    private ISeckillOrderService seckillOrderService;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    /**
     * 秒杀
     *开始抢购
     * @return
     */
    @GetMapping("/go/{userId}/{seckillId}/{uuid}")
    public Result seckill(
            @PathVariable("userId") Long userId,
            @PathVariable("seckillId") Long seckillId,
            @PathVariable(value = "uuid") String uuid) throws RemotingException, InterruptedException, MQClientException, MQBrokerException {
        Date now = new Date();
        //校验路径
        if (!seckillService.checkPath(userId, seckillId, uuid)) {
            logger.error("路径失效");
            return new Result(-1, "路径失效", null);
        }

        Integer count = (Integer) redisUtil.get(Constant.USER_SECKILL_COUNT + userId + "_" + seckillId);
        if (count != null) {
            //logger.error("你已经抢购过改商品");
            //return new Result(-1, "你已经抢购过改商品", null);
        }

        //获取商品信息
        final SeckillProductPreheatVO seckillProductPreheat = (SeckillProductPreheatVO)
                redisUtil.get(Constant.SECKILL_PRODUCT_INFO + seckillId);

        if (seckillProductPreheat == null) {
            logger.error("商品不存在");
            return new Result(-1, "商品不存在", null);
        }
        Date endTime = seckillProductPreheat.getEndTime();
        if (now.after(endTime)) {
            logger.error("秒杀时间已结束");
            return new Result(-1, "秒杀时间已结束", null);
        }
        Date startTime = seckillProductPreheat.getStartTime();
        if (now.before(startTime)) {
            logger.error("秒杀尚未开始");
            return new Result(-1, "秒杀尚未开始", null);
        }

        Integer number = seckillProductPreheat.getNumber();
        if (number == 0) {
            logger.error("库存不足");
            return new Result(-1, "库存不足", null);
        }

        // 从队列取出一个秒杀id 令牌
        Long seckillIdToken = seckillService.getOneSeckillToken(seckillId.toString());
        if (0 == seckillIdToken) {
            return new Result(-1, "商品被抢购完", null);
        }

        //以上走完，代表抢购成功。生成订单
        SeckillOrder seckillOrder = new SeckillOrder();
        final long seckillOrderId = SnowFlake.getNextId() ;
        seckillOrder.setSeckillOrderId(""+seckillOrderId);
        seckillOrder.setSeckillId(seckillId);
        seckillOrder.setUserId(userId);
        seckillOrder.setSeckillNumber(1);
        seckillOrder.setCreateTime(new Date());
        seckillOrder.setProductId(seckillProductPreheat.getProductId());


        //发送mq消息队列
        //RocketMQProducer.sendDelay("seckillTopic",String.valueOf(seckillOrderId),30);

        DefaultMQProducer producer = rocketMQTemplate.getProducer();
        Message message = new Message("seckillTopic",
                String.valueOf(seckillOrderId).getBytes(StandardCharsets.UTF_8));
        //设置延迟30秒
        //1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h
        message.setDelayTimeLevel(3);
        //发送
        producer.send(message, new SendCallback() {
            @Override
            public void onSuccess(SendResult sendResult) {
                logger.info("发送成功：{}", sendResult.toString());
                //发送成功后保存订单
                seckillOrderService.save(seckillOrder);
            }

            @Override
            public void onException(Throwable throwable) {
                logger.error("发送异常：{}", throwable.getMessage());
            }
        });

        //限制购买数量
        //过期时间
        //long exceed = (endTime.getTime() - now.getTime()) / 1000;
        //redisUtil.set(Constant.USER_SECKILL_COUNT + userId + "_" + seckillId, 1, exceed);
        logger.info("抢购成功，订单号：{}",""+seckillOrderId);
        return new Result(1, "秒杀成功", ""+seckillOrderId);
    }


    /**
     * 获取秒杀的path
     */
    @GetMapping("/getPath/{userId}/{seckillId}")
    public Result getSeckillPath(@PathVariable("seckillId") Long seckillId,
                                 @PathVariable("userId") Long userId) {
        if (seckillId == null || userId == null) {
            return new Result(-1, "参数缺失", null);
        }
        //生成一个随机串
        String path = seckillService.createseckillPath(userId, seckillId);
        if (path == null || "".equals(path)) {
            return new Result(-1, "尚未开始", null);
        }
        return new Result(1, "获取成功", path);
    }

}
